// Globals.
var i = 0;
var vis, tree, root, notes, video, tooltip;

// Constants.
var diagonal = d3.svg.diagonal.radial()
    .projection(function(d) {
        return [d.y, d.x / 180 * Math.PI]; });

var duration = d3.event && d3.event.altKey ? 5000 : 500;
var maxDepth = 3;

var Image = {
  CENTER: 'canada.jpg',
  PREFIX: 'canada_'
};

var Size = {
  IMAGE: 100,
  R_CIRCLE: 40,
  R_TREE: 480,
  ROOT: 100
};

// Methods.
function init() {
  createCenterNode();
  createTree();
}

function createCenterNode() {
  notes = document.getElementById('notes');
  notes.style.display = 'none';
  document.getElementById('notes-table').style.backgroundImage =
      'url("' + Image.CENTER + '")';

  video = document.getElementById('video');
  tooltip = document.getElementById('tooltip');
}

function createTree() {
  tree = d3.layout.tree()
    // 360 degrees, radial height is radius of the tree.
    .size([360, Size.R_TREE])
    .separation(function(a, b) {
        return (a.parent == b.parent ? 1 : 2) / a.depth;
    });

  vis = d3.select("#chart").append("svg")
    .attr("width", Size.R_TREE * 2)
    .attr("height", Size.R_TREE * 2)
  .append("g")
    // Center point of the tree is at [Size.R_TREE, Size.R_TREE]
    .attr("transform", "translate(" + Size.R_TREE + "," + Size.R_TREE + ")");

  d3.json("flare.js", function(json) {
    function toggleAll(d) {
      if (d.children) {
        d.children.forEach(toggleAll);
        toggle(d);
      }
    }

    root = json;
    root.x0 = 0;
    root.y0 = 0;
    root.children.forEach(toggleAll);
    update(root);
  });
}

/**
 * Compute the new tree layout.
 */
function update(source) {
  // Compute the new tree layout.
  var treeNodes = tree.nodes(root).reverse();
  treeNodes.forEach(function(d) {
    d.y = Size.R_TREE * d.depth / maxDepth + d.depth * 50;
    if (!d.x) {
      d.x = 0;
    }
    if (!d.y) {
      d.y = 0;
    }

    if (d.select) {
      video.style.display = d.video ? 'block' : 'none';
      notes.style.display = d.notes ? 'block' : 'none';

      if (d.notes) {
        notes.innerHTML = d.notes;
      } else if (d.video) {
        video.src = '//www.youtube.com/embed/' + d.movieid;
      }
    }
  });

  // Update the svg nodes.
  var gNodes = vis.selectAll("g.node")
      .data(treeNodes, function(d) {
            return d.id || (d.id = ++i); });
  updateNodeEnter(gNodes, source);
  updateNode(gNodes);
  updateNodeExit(gNodes, source);

  // Update the links.
  updateLinks(treeNodes, source);

  // Stash the old positions for transition.
  treeNodes.forEach(function(d) {
    d.x0 = d.x;
    d.y0 = d.y;
  });
}

/**
 * Transition nodes to their new position.
 */
function updateNode(gNodes) {
  /*
   *  var node = vis.selectAll("g.node")
      .data(nodes)
    .enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) {
        return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })

        */
  var nodeUpdate = gNodes.transition()
      .duration(duration)
      .attr("transform", function(d) {
          return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; });

  nodeUpdate.select("circle")
      .attr("r", function(d) {
        return d.root ? Size.ROOT : Size.R_CIRCLE; })
      .style("fill", function(d) {
          return d._children && d._children.length > 0 ? "lightsteelblue" : "#fff"; })
      .style("stroke", function(d) {
          if (d.video) {
            return '#fff';
          }
          if (d.select) {
            d.select = undefined;
            return '#f00';
          }
          return 'lightsteelblue'; });

  /*nodeUpdate.select("text")
      .style("fill-opacity", function(d) {
        console.log(d.stt);
        return d.stt ? 1 : 0; });  */
}

/**
 * Enter any new nodes at the parent's previous position.
 */
function updateNodeEnter(gNodes, source) {
  var nodeEnter = gNodes.enter().append("svg:g")
      .attr("class", "node")
      .attr("transform", function(d) {
          return "rotate(" + (source.x0 - 90) + ")translate(" + source.y0 + ")";
      })
      .on("click", function(d) {
          d.select = true;
          toggle(d);
          update(d);
      })
      .on("mouseover", function(d) {
        if (!d.tooltip) {
          tooltip.style.display = 'none';
          return;
        }
        var clientRect = this.getBoundingClientRect();
        tooltip.style.display = 'block';
        tooltip.innerHTML = d.tooltip;
        tooltip.style.top = (clientRect.top + 100) + 'px';
        tooltip.style.left = (clientRect.left + 100) + 'px';
      })
      .on("mouseout", function(d) {
        tooltip.style.display = 'none';
      });

  nodeEnter.append("svg:circle")
      .attr("r", 1e-6)
      .style('stroke', function(d) {
        return d.video ? '#fff' : 'lightsteelblue';
      })
      .style("fill", function(d) {
          return d._children && d._children.length > 0 ? "lightsteelblue" : "#fff";
      });

  nodeEnter.append("svg:image")
      .attr("xlink:href", function(d) {
        if (d.root) {
          return null;
        }
        if (d.video) {
          return 'http://img.youtube.com/vi/' + d.movieid + '/0.jpg';
        }
        return Image.PREFIX + d.name + '.png';
      })
      .attr("width",  Size.IMAGE)
      .attr("height", Size.IMAGE)
      .attr("transform", function(d) {
          if (d.root) {
            return '';
          }
          var degree = 90 - d.x;
          var shift = Size.R_CIRCLE + 7;
          return "rotate(" + degree + ")translate(-" + shift + ",-" + shift + ")";
      });

  /*nodeEnter.append("svg:foreignObject")
      .attr("width", 50)
      .attr("height", 50)
      .attr("transform", function(d) {
            var degree = 90 - d.x;
            var move = d.x < 180 ? Size.R_CIRCLE : -Size.R_CIRCLE;
            return "rotate(" + degree + ")translate(" + move + ")"; })
      .append("div")
          //.attr("xmlns", "http://www.w3.org/1999/xhtml")
          .attr("class", "tooltip")
          .html(function(d) { console.log("html", d.tooltip); return d.tooltip; })
          .text(function(d) { console.log("text", d.tooltip); return d.tooltip; });
          .attr("src", function(d) {
            return d.video ? d.src : "";
          })
          .attr("frameborder", 0);*/

  /*nodeEnter.append("svg:text")
      .attr("x", 0) //function(d) {
        //return d.children || d._children ? -10 : 10; })
          /*var shift = d.root ? 30 : 8;
          return d.x < 180 ? shift : -shift; }) */
      /*.attr("y", 0)
      .attr("text-anchor", function(d) {
          //return d.children || d._children ? "end" : "start"; })
          return d.x < 180 ? "end" : "start"; })
      .attr("transform", function(d) {
          //return d.x < 180 ? null : "rotate(180)"; })
          var degree = 90 - d.x;
          var move = d.x < 180 ? Size.R_CIRCLE : -Size.R_CIRCLE;
          return "rotate(" + degree + ")translate(" + move + ")"; })
      .text(function(d) { return d.tooltip; }); */
}

/**
 * Transition exiting nodes to the parent's new position.
 */
function updateNodeExit(gNodes, source) {
  var nodeExit = gNodes.exit().transition()
      .duration(duration)
      .attr("transform", function(d) {
          return "rotate(" + (source.x - 90) + ")translate(" + source.y + ")"; })
      .remove();

  nodeExit.select("circle")
      .attr("r", 1e-6);

  /*nodeExit.select("text")
      .style("fill-opacity", 1e-6);*/
}

function updateLinks(treeNodes, source) {
   /* var link = vis.selectAll("path.link")
      .data(tree.links(nodes))
    .enter().append("path")
      .attr("class", "link")
      .attr("d", diagonal);*/

  var link = vis.selectAll("path.link")
      .data(tree.links(treeNodes), function(d) { return d.target.id; });

  // Enter any new links at the parent's previous position.
  link.enter().insert("svg:path", "g")
      .attr("class", "link")
      .attr("d", function(d) {
          var o = {x: source.x0, y: source.y0};
          return diagonal({source: o, target: o});
      })
    .transition()
      .duration(duration)
      .attr("d", diagonal);

  // Transition links to their new position.
  link.transition()
      .duration(duration)
      .attr("d", diagonal);

  // Transition exiting nodes to the parent's new position.
  link.exit().transition()
      .duration(duration)
      .attr("d", function(d) {
          var o = {x: source.x, y: source.y};
          return diagonal({source: o, target: o});
      })
      .remove();
}

/**
 * Toggle children shown.
 * children are shown.  _children are hidden.
 */
function toggle(d) {
  if (d.children) {
    d._children = d.children;
    d.children = null;
  } else {
    d.children = d._children;
    d._children = null;
  }
}
